package fox.framework.rpc.converter;

import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.Serializer;
import de.javakaffee.kryoserializers.*;

import java.lang.reflect.InvocationHandler;
import java.net.URI;
import java.util.*;
import java.util.regex.Pattern;

/**
 * kryo序列化工厂
 * @author cuichao
 * @Description: KryoFactory
 * @Date: create in 2020/5/17 16:42
 */
public class KryoFactory extends KryoReflectionFactorySupport {

    public static ThreadLocal<Kryo> kryo = new InheritableThreadLocal<Kryo>(){
        @Override
        protected Kryo initialValue() {
            return new KryoFactory();
        }
    };


    public static Kryo get(){
        return kryo.get();
    }


    public KryoFactory(){
        //预注册
        register(Arrays.asList("").getClass(), new ArraysAsListSerializer());
        register(Collections.EMPTY_LIST.getClass(), new CollectionsEmptyListSerializer());
        register(Collections.EMPTY_MAP.getClass(), new CollectionsEmptyMapSerializer());
        register(Collections.EMPTY_SET.getClass(), new CollectionsEmptySetSerializer());
        register(Collections.singletonList("").getClass(), new CollectionsSingletonListSerializer());
        register(Collections.singleton("").getClass(), new CollectionsSingletonSetSerializer());
        register(Collections.singletonMap("", "").getClass(), new CollectionsSingletonMapSerializer());
        register(Pattern.class, new RegexSerializer());
        register(BitSet.class, new BitSetSerializer());
        register(URI.class, new URISerializer());
        register(UUID.class, new UUIDSerializer());
        register(GregorianCalendar.class, new GregorianCalendarSerializer());
        register(InvocationHandler.class, new JdkProxySerializer());

        UnmodifiableCollectionsSerializer.registerSerializers(this);
        SynchronizedCollectionsSerializer.registerSerializers(this);
        //开启循环引用解析
        setReferences(true);
        //关闭只能序列化已注册的类
        setRegistrationRequired(false);
    }


    @Override
    @SuppressWarnings({"rawtypes", "unchecked"})
    public Serializer<?> getDefaultSerializer(Class clazz)
    {
        if(EnumSet.class.isAssignableFrom(clazz))
            return new EnumSetSerializer();

        if(EnumMap.class.isAssignableFrom(clazz))
            return new EnumMapSerializer();

        if(Collection.class.isAssignableFrom(clazz))
            return new CopyForIterateCollectionSerializer();

        if(Map.class.isAssignableFrom(clazz))
            return new CopyForIterateMapSerializer();

        if(Date.class.isAssignableFrom(clazz))
            return new DateSerializer( clazz );

        if (SubListSerializers.ArrayListSubListSerializer.canSerialize(clazz)
                || SubListSerializers.JavaUtilSubListSerializer.canSerialize(clazz))
            return SubListSerializers.createFor(clazz);

        return super.getDefaultSerializer(clazz);
    }

}
